import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
import HelloWorld from '@/components/HelloWorld.vue';

// 路由跳转

// 字符串路径
// router.push('/users/eduardo')

// 带有路径的对象
// router.push({ path: '/users/eduardo' })

// 命名的路由，并加上参数，让路由建立 url
// router.push({ name: 'user', params: { username: 'eduardo' } })

// 带查询参数，结果是 /register?plan=private
// router.push({ path: '/register', query: { plan: 'private' } })

// 带 hash，结果是 /about#team
// router.push({ path: '/about', hash: '#team' })


// const username = 'eduardo'
// 我们可以手动建立 url，但我们必须自己处理编码
// router.push(`/user/${username}`) // -> /user/eduardo

// 同样
// router.push({ path: `/user/${username}` }) // -> /user/eduardo

// 如果可能的话，使用 `name` 和 `params` 从自动 URL 编码中获益
// router.push({ name: 'user', params: { username } }) // -> /user/eduardo


// 替换当前位置

// router.push({ path: '/home', replace: true })

// 相当于
// router.replace({ path: '/home' })


// @ts-ignore
const routes: Array<RouteRecordRaw> = [
  {
    path: '',
    redirect: (_) => {
      return { path: '/home' };
    }
  },
  {
    path: '/home',
    name: 'HelloWorld',
    component: HelloWorld,
    // 路由独享的守卫
    // 只在进入路由时触发，不会在 params、query 或 hash 改变时触发。
    // beforeEnter: (to, from) => {
    //   return false
    // }, 

    // meta: { requiresAuth: true }
  },
  {
    path: '/about',
    name: 'About',
    component: () =>
      import(/* webpackChunkName: "About" */ '@/pages/About.vue'),
  },
  {
    path: '/:currentPath(.*)*', // 路由未匹配到，进入这个
    redirect: (_) => {
      return { path: '/404' };
    }
  }
];

const router = createRouter({
  history: createWebHistory(''),
  routes,
  // 使用前端路由，当切换到新路由时，想要页面滚到顶部，或者是保持原先的滚动位置，就像重新加载页面那样
  scrollBehavior(to, from, savedPosition) {
    return {
      el: '#app',
      // 也可以这么写
      // el: document.getElementById('main'),
      // el: '#main',
      top: 0,
      behavior: 'smooth'
    };
  },
  // strict: true   // 为true时，路由匹配规则区分大小写
});

// 全局前置守卫
router.beforeEach((to, from, next) => {
  // to: 即将要进入的目标 用一种标准化的方式
  // from: 当前导航正要离开的路由 用一种标准化的方式

  next()

  // next({ name: 'Login' })

  // return
  // return true
  // return '/login'

  // return { 
  //    name: 'Login',
  //    replace: true,
  //    path:'/'
  // }

  // 返回 false 以取消导航
  // return false

})

// 全局解析守卫
router.beforeResolve(async to => {
  if (to.meta.requiresCamera) {
    try {
      // await askForCameraPermission()
    } catch (error) {
      if (error instanceof NotAllowedError) {
        // ... 处理错误，然后取消导航
        return false
      } else {
        // 意料之外的错误，取消导航并把错误传给全局处理器
        throw error
      }
    }
  }
})

// 全局后置钩子
// 你也可以注册全局后置钩子，然而和守卫不同的是，这些钩子不会接受 next 函数也不会改变导航本身：
// 它们对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用。
// 它们也反映了 navigation failures 作为第三个参数：
router.afterEach((to, from, failure) => {
})

// 如果遇到了意料之外的情况，可能会抛出一个 Error。这会取消导航并且调用
router.onError((err) => {
  console.log(err, 'router.onError  err')
})



export default router;


// vue文件内

// beforeRouteEnter(to, from) {
//   // 在渲染该组件的对应路由被验证前调用
//   // 不能获取组件实例 `this` ！
//   // 因为当守卫执行时，组件实例还没被创建！
// }

// beforeRouteUpdate(to, from) {
//   // 在当前路由改变，但是该组件被复用时调用
//   // 举例来说，对于一个带有动态参数的路径 `/users/:id`，在 `/users/1` 和 `/users/2` 之间跳转的时候，
//   // 由于会渲染同样的 `UserDetails` 组件，因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
//   // 因为在这种情况发生的时候，组件已经挂载好了，导航守卫可以访问组件实例 `this`
// }

// beforeRouteLeave(to, from) {
//   // 在导航离开渲染该组件的对应路由时调用
//   // 与 `beforeRouteUpdate` 一样，它可以访问组件实例 `this`
// }

// 完整的导航解析流程
// 导航被触发。
// 在失活的组件里调用 beforeRouteLeave 守卫。
// 调用全局的 beforeEach 守卫。
// 在重用的组件里调用 beforeRouteUpdate 守卫(2.2+)。
// 在路由配置里调用 beforeEnter。
// 解析异步路由组件。
// 在被激活的组件里调用 beforeRouteEnter。
// 调用全局的 beforeResolve 守卫(2.5+)。
// 导航被确认。
// 调用全局的 afterEach 钩子。
// 触发 DOM 更新。
// 调用 beforeRouteEnter 守卫中传给 next 的回调函数，创建好的组件实例会作为回调函数的参数传入。